package com.jadesoft.listener;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.log4j.Logger;
import org.springframework.util.Assert;

import com.jadesoft.common.service.PaginationService;
import com.jadesoft.stock.FetionHelper;
import com.jadesoft.stock.entity.StockPrice;
import com.jadesoft.stock.util.Constants;
import com.jadesoft.stock.util.FileUtil;
import com.jadesoft.stock.util.StockUtil;

/**
 * 1.查询最新的股票及价格保存到DB
 * 2.将最新的股票信息更新到stock-list.js文件
 * @author YZT
 */
public class StockTask extends TimerTask {
	private Logger logger = Logger.getLogger(StockTask.class);
	private PaginationService persistence = new PaginationService();
	private Map<String, StockPrice> stockMap = new HashMap<String, StockPrice>();

	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public void run() {
		logger.debug(Calendar.getInstance());
		// 1. 判断今天是否是交易日
		if (StockUtil.isNotDayTrading()){
			logger.info("date: "+new Date() + " is not day trading ");
			return;
		}

		// 2.发送HTTP请求,获取最新的股票价格存储到DB
		this.getAndSaveData();

		// 3.更新股票代码,股票名称到stock-list.js文件 --->修改为通过HTTP请求获取JS
		this.updateStockListFile();
		
		// 4.生成LIST(MobileNo,content)
		List result = this.createMsgList();
		FetionHelper.sendMsg(result);
		
		// 5.clear stock map
		this.stockMap.clear();
	}

	// 获取股票信息
	public void getAndSaveData() {
		/**
		 * styles = { "10", "11", "20", "21", "26", "27" ,"33"};//
		 * 沪A,沪B,深A,深B,中小板,创业板,(中小,创业都属于深圳股市),沪A+深A
		 */
		String[] styles = { "10", "11", "20", "21" };
		HttpClient client = new HttpClient();
		/******* HTTP REQUEST 代理设置 ********/
//		client.getHostConfiguration().setProxy("11.133.190.13", 8080);
//		client.getHostConfiguration().setProxy("127.96.172.63", 8888);
		for (int i = 0; i < styles.length; i++) {
			String uri = "http://hqdigi2.eastmoney.com/EM_Quote2010NumericApplication/index.aspx?"
					+ "type=s&sortType=C&sortRule=-1&pageSize=20000&page=1&jsName=quote_123&style=";
			uri += styles[i];
			BufferedReader reader = null;
			GetMethod method = new GetMethod(uri);
			try {
				int returnCode = client.executeMethod(method);
				if (returnCode == HttpStatus.SC_NOT_IMPLEMENTED) {
					logger.error("The get method is not implemented by this URI");
					method.getResponseBodyAsString();
				} else {
					reader = new BufferedReader(new InputStreamReader(
							method.getResponseBodyAsStream(), "utf-8"));
					String readLine;
					String text = "";
					while (((readLine = reader.readLine()) != null)) {
						text += readLine;
					}
					// 解析并保存返回数据
					this.persistence.saveObjs(this.parseText(text).toArray());
				}
			} catch (Exception e) {
				logger.error(e);
			} finally {
				method.releaseConnection();
				if (reader != null)
					try {
						reader.close();
					} catch (Exception fe) {
						logger.error(fe);
					}
			}
		}
	}

	/**
	 * 将返回的字符串转换成相应的对象
	 * 
	 * @throws ParseException
	 */
	public List<StockPrice> parseText(String text) throws ParseException {
		/**
		 * 6015181,601518,吉林高速,3.98,4.07, 4.13,4.19,3.94,33497,828936,
		 * 0.15,3.77%,4.04,6.28%,-15.10%, -6430,295,357110,471826,1,
		 * -1,-0.72%,7.65,13.45%,13.55,
		 * 001148|002421|003501|003552|003593,4.14,4.15,2011-05-04 15:03:05,0,
		 * 616396393" 序号 代码 名称 相关资讯 最新价 涨跌额 涨跌幅 振幅 成交量(手) 成交额(万) 昨收 今开 最高 最低
		 * 5分钟涨跌 加自选 601518 吉林高速吧 资讯 档案 4.13 0.15 3.77% 6.28% 828936 33497 3.98
		 * 4.07 4.19 3.94 -0.72% 1 2 ['no','代码','名称','昨收','今开',
		 * '最新','最高','最低','成交额(万)','成交量(手)', '涨跌额','涨跌幅','no','振幅',]
		 */
		String str = text.substring(text.indexOf("[") + 1, text.indexOf("]"));
		if (str.startsWith("\""))
			str = str.substring(1);
		if (str.endsWith("\""))
			str = str.substring(0, str.length() - 1);
		String[] stocks = str.split("\",\"");
		String[] a = null;
		StockPrice bo = null;
		SimpleDateFormat formattor = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		for (int i = 0; i < stocks.length; i++) {
			a = stocks[i].split(",");
			bo = new StockPrice();
			bo.setSymbol(a[1]);
			bo.setName(a[2]);
			bo.setPrevClose(new Double(a[3]));
			bo.setOpen(new Double(a[4]));
			bo.setLastTrade(new Double(a[5]));
			bo.setHighest(new Double(a[6]));
			bo.setLowest(new Double(a[7]));
			bo.setTurnover(new Double(a[8]));
			bo.setVolume(new Integer(a[9]));
			bo.setChanged(a[10]);
			bo.setChangePer(a[11]);
			bo.setSwing(a[13]);
			bo.setAchieveDate(formattor.parse(a[28]));
			this.stockMap.put(bo.getSymbol(), bo);// 发消息用
		}
		logger.info("股票数: " + stockMap.size());
		return new ArrayList<StockPrice>(stockMap.values());
	}

	/**
	 * query subscript data ,create content
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List createMsgList() {
		List result = new ArrayList();
		String sql = " SELECT a.mobile_no,b.symbols" +
					"	 FROM (SELECT user_id,GROUP_CONCAT(stock_symbol) AS symbols  " +
					"			FROM stock_subscript group by user_id) AS b," +
					" user AS a" +
					" WHERE a.id = b.user_id" +
					" AND a.mobile_no IS NOT NULL";
		logger.debug(sql);
		List<Object[]> list = this.persistence.queryBySql(sql);
		String fetionNo = null;
		String content = null;
		for (int i = 0; i < list.size(); i++) {
			try {
				fetionNo = list.get(i)[0].toString();
				content = getContent(list.get(i)[1].toString().split(","));
				result.add(new String[]{fetionNo,content.replace(" ", "")});
			} catch (Exception e) {
				logger.error(e);
			}
		
		}
		logger.info("股票短线总条数:"+result.size());
		return result;
	}

	/**
	 * 参数是分组合并后的对象
	 * 
	 * @param symbols
	 *            "600000,600001"
	 * @return
	 */
	public String getContent(String[] symbols) {
		String text = "";
		for (String smb : symbols) {
			text += this.getText(smb);
		}
		return text;
	}

	/**
	 * 根据STOCK编号组织信息内容
	 * 
	 * @param symbole
	 *            stock 编码
	 * @return
	 */
	public String getText(String symbole) {
		StockPrice price = this.stockMap.get(symbole);
		Assert.notNull(price,symbole+"不存在");
		String text = "";
		text += price.getName() + "(" + price.getSymbol() + ") ";
		text += "昨收:" + price.getLastTrade() + ",";
		text += "今开:" + price.getOpen() + ",";
		text += "当前:" + price.getLastTrade() + ",";
		return text;
	}

	public void updateStockListFile() {
		String dir = FileUtil.getRootDir() + Constants.JS_PATH
				+ Constants.STOCK_LIST_NAME;
		// 1.delete old file
		File file = new File(dir);
		file.deleteOnExit();
		
		//2.create new file
		Writer writer = null;
		try {
			file.createNewFile();
			writer = new OutputStreamWriter(new FileOutputStream(file),
					Constants.CHAR_SET);
			writer.append("var STOCK_LIST = [");
			writer.append(this.getArrayText());
			writer.append("];");
			writer.flush();
		} catch (IOException e) {
			logger.error(e);
		} finally {
			if (writer != null)
				try {
					writer.close();
				} catch (IOException e) {
					logger.error(e);
				}
		}
		logger.info("create fund-list.js: " + dir);

	}

	public String getArrayText() {
		String text = "";
		Iterator<StockPrice> iterator = this.stockMap.values().iterator();
		StockPrice bo = null;
		while (iterator.hasNext()) {
			bo = iterator.next();
			text += "'" + bo.getName() + "(" + bo.getSymbol() + ")',";
		}
		return text;
	}
	
	public static void main(String[] args) {
		StockTask task = new StockTask();
		task.run();
	}
	
}

